<!-- 裁剪图片弹窗组件 -->
<template>
  <a-modal :maskClosable="false" :title="title" centered :width="860" v-model="open" :footer="null">
    <a-spin :spinning="loading" tip="正在上传中...">
      <div class="disFlx">
        <div style="width: 400px; height: 400px">
          <vue-cropper
            v-if="visible"
            ref="cropper"
            outputType="png"
            :img="options.img"
            :info="true"
            :autoCrop="true"
            :centerBox="false"
            :infoTrue="true"
            :canMoveBox="false"
            :canMove="options.canMove"
            :fixedBox="options.fixedBox"
            :fixed="options.fixed"
            :fixedNumber="options.fixedNumber"
            :autoCropWidth="400 * options.fixedNumber[0]"
            :autoCropHeight="400 * options.fixedNumber[1]"
            mode="100%"
            :enlarge="enlarge"
            @realTime="realTime"
          />
        </div>
        <div style="width: 400px; height: 400px;background-color: #fafafa;" class="disFlxCC _ml-10">
          <div class="imgUploadPreview" :style="`width:${previews.w || width}px;height:${previews.h || height}px;border-radius:${borderRadius};`">
            <img :src="previews.url" :style="previews.img" />
          </div>
        </div>
      </div>

      <div class="disFlxJS _mt-20">
        <div class="disFlxAC">
          <a-upload :accept="fileType.join(',')" action="#" :showUploadList="false" :before-upload="beforeUpload">
            <a-button icon="upload">重选图片</a-button>
          </a-upload>

          <a-button icon="plus" class="_ml-10" @click="changeScale(1)">放大</a-button>
          <a-button icon="minus" class="_ml-10" @click="changeScale(-1)">缩小</a-button>
          <a-button icon="undo" class="_ml-10" @click="rotateLeft()">向左旋转</a-button>
          <a-button icon="redo" class="_ml-10" @click="rotateRight()">向右旋转</a-button>
          <a-button icon="sync" class="_ml-10" @click="resetImage()">重置图片</a-button>
        </div>

        <a-button type="primary" @click="uploadImg()">提 交</a-button>
      </div>
    </a-spin>
  </a-modal>
</template>

<script>
// https://github.com/xyxiao001/vue-cropper
import { VueCropper } from 'vue-cropper'
import { customUpload, uploadApi } from '@/api/upload'

export default {
  components: { VueCropper },
  props: {
    // 上传类型范围 例如['.png', '.jpg', '.jpeg'] || ['.mp4']
    fileType: {
      type: Array,
      default: () => ['.png', '.jpg', '.jpeg']
    },
    // 图片大小限制 M
    fileSize: {
      type: Number,
      default: 10
    },
    // 图片宽度
    width: {
      type: Number,
      default: 104
    },
    // 图片高度
    height: {
      type: Number,
      default: 104
    },
    // 圆角
    borderRadius: {
      type: String,
      default: ""
    },
    // 输出比列倍数
    enlarge: {
      type: Number,
      default: 1
    }
  },
  mounted() {
    this.options.fixedNumber = [(this.width / this.height), 1];
  },
  watch: {
    width(val){
      this.options.fixedNumber = [(val / this.height), 1];
    },
    height(val){
      this.options.fixedNumber = [(this.width / val), 1];
    },
  },
  data() {
    return {
      open: false,
      // 是否显示cropper
      visible: false,
      // 弹出层标题
      title: '裁剪图片',
      options: {
        img: "", //裁剪图片的地址
        canMove: true,// 图片是否可以拖动
        fixedBox: true, // 不允许改变截图框大小
        fixed: true, // 否开启截图框宽高固定比例
        fixedNumber: [1, 1], // 等比缩放比例 [宽度, 高度]
      },
      previews: {},
      loading: false,
    }
  },
  methods: {
    // url 默认裁剪图片
    show(url) {
      this.open = true
      this.$nextTick(() => {
        this.visible = true;
        url = url.replace(/(\?|#)[^'"]*/, '')
        this.options.img = url ? url + '?time=' + Date.parse(new Date()) : "";
      })
    },
    // 向左旋转
    rotateLeft() {
      this.$refs.cropper.rotateLeft()
    },
    // 向右旋转
    rotateRight() {
      this.$refs.cropper.rotateRight()
    },
    // 图片缩放
    changeScale(num) {
      num = num || 1
      this.$refs.cropper.changeScale(num)
    },
    // 上传预处理
    beforeUpload(file) {
      const upfileScope = this.fileType.map(v => 'image/' + v.replace('.', ''))
      const isImgType = upfileScope.includes(file.type)
      if (!isImgType) {
        this.$message.error(`请上传${this.fileType.join(' ')}格式的图片!`)
        return false
      }
      const isImgSize = file.size / 1024 / 1024 < this.fileSize
      if (!isImgSize) {
        this.$message.error(`图片大小不能超过${this.fileSize}M!`)
        return false
      }
      const reader = new FileReader()
      reader.readAsDataURL(file)
      reader.onload = () => {
        this.options.img = reader.result
      }
    },
    // 上传图片
    uploadImg() {
      const that = this;
      that.loading = true;
      try {
        that.$refs.cropper.getCropBlob(data => {
          // blob转为file
          const files = new window.File([data], `${Date.parse(new Date())}_cropper_${data.type.replace('/','.')}`, { type: data.type });
          const formData = new FormData()
          formData.append('file', files)
          customUpload(uploadApi.customImg, formData).then(res => {
            that.$emit('success', res.data.imagePathBig);
            that.loading = false;
            that.open = false;
            that.visible = false;
          }).catch(()=>{
            that.loading = false;
          })
        })
      } catch (err) {
        this.loading = false;
      }
    },
    // 实时预览
    realTime(data) {
      this.previews = data
    },
    // 重置图片
    resetImage() {
      this.$refs.cropper.reload();
    }
  }
}
</script>
<style scoped lang="less">
.imgUploadPreview {
  box-shadow: 0 0 4px #ccc;
  overflow: hidden;
}
</style>
